package com.caocaog.market.finance.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.caocaog.market.constant.MarketConstant;
import com.caocaog.market.entity.ShopBasic;
import com.caocaog.market.finance.entity.MkBillChange;
import com.caocaog.market.finance.entity.MkBillLine;
import com.caocaog.market.finance.entity.MkBillLineHistory;
import com.caocaog.market.finance.mapper.MkBillChangeMapper;
import com.caocaog.market.finance.mapper.MkBillLineHistoryMapper;
import com.caocaog.market.finance.mapper.MkBillLineMapper;
import com.caocaog.market.finance.pay.FinanceUnionPay;
import com.caocaog.market.finance.service.IMkBillChangeService;
import com.caocaog.market.finance.service.MkBillLineService;
import com.caocaog.market.finance.vo.SysCheckVo;
import com.caocaog.market.service.IShopBasicService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.oConvertUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author liguang
 * @version 1.0.0
 * @Project jeecg-boot
 * @Package com.caocaog.market.finance.service.impl
 * @ClassName MkBillHistoryServiceImpl.java
 * @createTime 2021年12月03日 19:25:00
 * @Description TODO
 */
@Slf4j
@Service
public class MkBillLineServiceImpl extends ServiceImpl<MkBillLineMapper , MkBillLine> implements MkBillLineService {
    @Resource
    private MkBillLineMapper billLineMapper;
    @Autowired
    private FinanceUnionPay financeUnionPay;

    @Resource
    private MkBillLineHistoryMapper billLineHistoryMapper;

    @Autowired
    private MkBillChangeMapper mkBillChangeMapper;

    @Resource
    private IMkBillChangeService mkBillChangeService;

    @Resource
    private IShopBasicService shopBasicService;

    @Override
    public IPage<MkBillLine> findForPage(Page<MkBillLine> page, MkBillLine billLine) {
        return billLineMapper.findForPage(page, billLine);
    }



    @Override
    public List<SysCheckVo> findSysCheckVoList() {
        return billLineMapper.findSysCheckVoList();
    }

    @Override
    public List<MkBillLine> findForPage(MkBillLine billLine) {
        return billLineMapper.findForPage(billLine);
    }


    /**
     * 提现申请,qiu
     * date: 20220729
     */
    @Override
    @Transactional
    public int applyForWithdrawCash(MkBillLine billLine, Integer nextStatus) {
        LoginUser currentUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        String rejectReason = billLine.getWithdrawRejectReason();
        billLine.setWithdrawRejectReason(null);
        System.out.println(billLine.getWithdrawCashStatus() +"   "+billLine.getId());

        List<MkBillLine> applications = this.findForPage(billLine);
        List<MkBillLineHistory> billLineHistories = new ArrayList<MkBillLineHistory>();
        Date date = new Date();
        List<String> orderNoList = new ArrayList<>();
        BigDecimal total = new BigDecimal("0.00");
        for (MkBillLine line : applications) {
            MkBillLineHistory history = new MkBillLineHistory();
            BeanUtils.copyProperties(line, history);
            history.setId(IdWorker.getIdStr(history));
            history.setDelFlag(0);
            history.setBillLineId(line.getId());
            history.setCreateTime(date);
            history.setCreateBy(currentUser.getUsername());
            history.setLockVersion(line.getLockVersion() + 1);
            history.setWithdrawCashStatus(nextStatus);
            if(nextStatus.equals(MarketConstant.FINANCE_BILL_LINE_WITHDRAW_CASH_YSQDSH)){
                history.setWithdrawTime(date);
                history.setAuditNo(billLine.getAuditNo());
            }
            if(nextStatus.equals(MarketConstant.FINANCE_BILL_LINE_WITHDRAW_CASH_SHTGDZZ)){
                history.setWithdrawApplyCheckTime(date);
            }
            if (StringUtils.isNotBlank(rejectReason)) {
                // 这个只有在提现申请被拒绝之后，才会用到
                history.setWithdrawRejectReason(rejectReason);
            }
            // 下面两个是提现成功之后，需要用到的   ：ali_order_no(支付宝订单号)    ali_relt（调用支付宝返回的结果）
            history.setAliOrderNo(billLine.getAliOrderNo());
            history.setAliRelt(billLine.getAliRelt());
            billLineHistories.add(history);
            orderNoList.add(line.getOrderNo());
            total = total.add( new BigDecimal(line.getRakeAmount()));
        }

        if (orderNoList.size() < 1) {
            return 0;
        }
        String shopName = currentUser.getUsername();

        if (billLine.getType() == MarketConstant.USER_TYPE_MERCHANT){
            ShopBasic shopBasic = shopBasicService.selectOneByUserForServe();
            shopName= shopBasic.getName();
        }

        //往提现关联表插入数据
        MkBillChange mkbillchange = new MkBillChange();

        mkbillchange.setShopName(shopName);
        mkbillchange.setChangeValue(String.valueOf(total));
        mkbillchange.setCreateBy(currentUser.getUsername());
        mkbillchange.setChangeNo(DateUtils.date2Str(new Date(), DateUtils.yymmddhhmmssSSSSS.get()));
        mkbillchange.setType(billLine.getType());
        mkbillchange.setCreateTime(date);
        if(billLine.getSiteId() != null){
            mkbillchange.setSiteId(billLine.getSiteId());
        }
        else{
            mkbillchange.setMerchantId(billLine.getMerchantId());
        }
        mkBillChangeMapper.insert(mkbillchange);
        Integer changeId = mkbillchange.getId();

        //根据订单号更改申请提现的状态并添加关联changeId
        LambdaUpdateWrapper<MkBillLine> mkBillLineLambdaUpdateWrapper = new LambdaUpdateWrapper<>();

        mkBillLineLambdaUpdateWrapper.set(MkBillLine::getWithdrawCashStatus , MarketConstant.FINANCE_BILL_LINE_WITHDRAW_CASH_YSQDSH)
                .set(MkBillLine::getBillChangeId, changeId)
                .set(MkBillLine::getWithdrawTime, date)
                .in(MkBillLine::getOrderNo, orderNoList)
                .eq(MkBillLine::getType, billLine.getType());
        this.update(mkBillLineLambdaUpdateWrapper);

        if (null == billLineHistories || billLineHistories.size() < 1) {
            return 0;
        }

        return billLineHistoryMapper.insertBatchSomeColumn(billLineHistories);
    }

    /**
     * 审核功能,qiu 20220729
     */
    @Override
    @Transactional
    public  boolean checkBillChange(MkBillChange billChange){

        LambdaUpdateWrapper<MkBillChange> billChangeWapper = new LambdaUpdateWrapper<>();
        billChangeWapper.set(MkBillChange::getWithdrawCashStatus, billChange.getWithdrawCashStatus())
                        .eq(MkBillChange::getId, billChange.getId());
        mkBillChangeMapper.update(billChange,billChangeWapper);

        LambdaUpdateWrapper<MkBillLine> mkBillLineLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        mkBillLineLambdaUpdateWrapper.set(MkBillLine::getWithdrawCashStatus, billChange.getWithdrawCashStatus())
                                     .eq(MkBillLine::getBillChangeId, billChange.getId());


        return this.update(mkBillLineLambdaUpdateWrapper);
    }

    /**
     * 提现申请、审核通过、只是状态的改变
     * 驳回  状态和原因的改变；只要有一单有问题被驳回了   那么所有的提现账单行都被驳回
     * 已提现：相对复杂
     * 涉及到的字段：ali_order_no    ali_relt
     */
    @Override
    public int withdrawCashApplication(MkBillLine billLine, Integer nextStatus) {
        LoginUser currentUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        String rejectReason = billLine.getWithdrawRejectReason();
        billLine.setWithdrawRejectReason(null);
        System.out.println(billLine.getWithdrawCashStatus() +"   "+billLine.getId());

        List<MkBillLine> applications = this.findForPage(billLine);
        List<MkBillLineHistory> billLineHistories = new ArrayList<MkBillLineHistory>();
        Date date = new Date();
        List<String> orderNoList = new ArrayList<>();
        for (MkBillLine line : applications) {
            MkBillLineHistory history = new MkBillLineHistory();
            BeanUtils.copyProperties(line, history);
            history.setId(IdWorker.getIdStr(history));
            history.setBillLineId(line.getId());
            history.setCreateTime(date);
            history.setCreateBy(currentUser.getUsername());
            history.setLockVersion(line.getLockVersion() + 1);
            history.setWithdrawCashStatus(nextStatus);
            if(nextStatus.equals(MarketConstant.FINANCE_BILL_LINE_WITHDRAW_CASH_YSQDSH)){
                history.setWithdrawTime(date);
                history.setAuditNo(billLine.getAuditNo());
            }
            if(nextStatus.equals(MarketConstant.FINANCE_BILL_LINE_WITHDRAW_CASH_SHTGDZZ)){
                history.setWithdrawApplyCheckTime(date);
            }
            if (StringUtils.isNotBlank(rejectReason)) {
                // 这个只有在提现申请被拒绝之后，才会用到
                history.setWithdrawRejectReason(rejectReason);
            }
            // 下面两个是提现成功之后，需要用到的   ：ali_order_no(支付宝订单号)    ali_relt（调用支付宝返回的结果）
             history.setAliOrderNo(billLine.getAliOrderNo());
             history.setAliRelt(billLine.getAliRelt());
            billLineHistories.add(history);
            orderNoList.add(line.getOrderNo());
        }
        if (null == billLineHistories || billLineHistories.size() < 1) {
            return 0;
        }

        return billLineMapper.dealWithdrawCashApplication(billLineHistories);

    }

    @Override
    public int batchWithdrawCashApplication(List<SysCheckVo> sysCheckVos, Integer nextStatus) {
        int count = 0;
        List<MkBillLine> mkBillLineList = new ArrayList<>();
        List<String> auditNoList = sysCheckVos.stream().map(SysCheckVo::getAuditNo).collect(Collectors.toList());
        mkBillLineList = this.billLineMapper.selectList(new LambdaQueryWrapper<MkBillLine>()
        .in(MkBillLine::getAuditNo,auditNoList));

        for (MkBillLine mkBillLine: mkBillLineList) {
            if (mkBillLine.getWithdrawCashStatus().equals(3)){
                log.info("总部-财务账单审核-单号:"+mkBillLine.getAuditNo()+"-"+mkBillLine.getId()+"-"+mkBillLine.getWithdrawCashStatus()+"已审核通过,跳过此循环");
                continue;
            }
            if (!(mkBillLine.getWithdrawCashStatus().equals(2)|| mkBillLine.getWithdrawCashStatus().equals(4))){
                log.info("总部-财务账单审核-单号:"+mkBillLine.getAuditNo()+"-"+mkBillLine.getId()+"-"+mkBillLine.getWithdrawCashStatus()+"并不是待审核或者驳回的状态");
                continue;
            }
            count = count + this.withdrawCashApplication(mkBillLine, nextStatus);
        }
        return count;
    }

    @Override
    public int batchWithdrawCashApplications(List<MkBillLine> billLine, Integer nextStatus) {
        return 0;
    }

    @Override
    public Integer batchWithdrawById(List<String> idList) {
        List<MkBillLine> orderList = billLineMapper.selectBatchIds(idList);
        List<String> changedIdList = new ArrayList<>();
        orderList.stream().filter(o->o.getWithdrawCashStatus().equals(3)).forEach(o->{
            changedIdList.add(o.getId());
        });
        Integer count = 0;
//        if(changedIdList.size() > 0){
//            count = billLineMapper.updateStatusById(changedIdList, 5);
//        }
        return count;
    }

    @Override
    public String transfer(String billLineId) {
        MkBillLine billLineOld = billLineMapper.selectById(billLineId);
        if (oConvertUtils.isEmpty(billLineOld)) {
            throw new JeecgBootException("转账失败, 未查询到账单信息, billLineId-> " + billLineId);
        }
        if (oConvertUtils.isEmpty(billLineOld.getWithdrawCashStatus())
                || !MarketConstant.FINANCE_BILL_LINE_WITHDRAW_CASH_SHTGDZZ.equals(billLineOld.getWithdrawCashStatus())) {
            log.error("billLineOld: " + billLineOld);
            throw new JeecgBootException("转账失败, 当前账务模块账单行的状态(withdrawCashStatus)不是 3(提现申请审核通过待转账)");
        }

        LoginUser currentUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        //已审核待结算转账 go onFinancePay.transfer 未返回数据
        //todo 转账 check 单笔转账上下限 暂不设置
        Map<String, Object> resultMap = financeUnionPay.transfer(billLineOld.getOrderNo(), billLineOld.getRakeAliname(), billLineOld.getRakeAlipay(),
                billLineOld.getRakeAmount(), billLineOld.getMark(), billLineOld.getType());
        if (Boolean.TRUE.equals(resultMap.get("isSuccess"))) {
            //转账成功
            billLineOld.setWithdrawCashStatus(MarketConstant.FINANCE_BILL_LINE_WITHDRAW_CASH_YTX);
           /* billLineOld.setAliOrderNo(result.get("aliOrderNo").toString());*/
            log.info("------transfer-----已成功到账 ---开始更新状态和新增历史记录-----" + billLineOld.getId());
        } else {
            //转账失败时 无需更新状态 还是[3提现申请审核通过待转账]
            log.info("------transfer-----转账失败啦 ---开始更新状态和新增历史记录-----" + billLineOld.getId());
            throw new JeecgBootException(String.valueOf(resultMap.get("sub_msg")));
        }
        /* billLineOld.setAliRelt(result.toString());*/
        MkBillLineHistory his = new MkBillLineHistory();
        BeanUtils.copyProperties(billLineOld, his);
        his.setId(IdWorker.getIdStr(his));
        his.setBillLineId(billLineOld.getId());
        his.setCreateTime(new Date());
        his.setCreateBy(currentUser.getUsername());
        his.setLockVersion(billLineOld.getLockVersion() + 1);
        List<MkBillLineHistory> billLineHistories = new ArrayList<>();
        billLineHistories.add(his);
        billLineMapper.dealWithdrawCashApplication(billLineHistories);
        return String.valueOf(resultMap.get("msg"));
    }

    @Override
    @Transactional
    public boolean transferAll(Integer id){
        LambdaQueryWrapper<MkBillLine> mkBillLine = new LambdaQueryWrapper<MkBillLine>().eq(MkBillLine::getBillChangeId, id);
        List<MkBillLine> mkBillLineList = super.baseMapper.selectList(mkBillLine);
        BigDecimal limit = new BigDecimal("0.1");
        for (MkBillLine line : mkBillLineList) {
            BigDecimal amount = new BigDecimal(line.getRakeAmount());
            int i = amount.compareTo(limit);
            if( i >= 0){
                this.transfer(line.getId());
            }
        }

        mkBillChangeService.update(null, new LambdaUpdateWrapper<MkBillChange>()
                .set(MkBillChange::getWithdrawCashStatus, 5)
                .eq(MkBillChange::getId, id));

        return true;
    }

    /**
     * 根据id进行审核
     * @param billLine
     * @return
     */
    @Override
    @Transactional
    public int checkApplication(MkBillLine billLine) {
        Date date = new Date();
        UpdateWrapper<MkBillLine> updateWrapper= new UpdateWrapper<MkBillLine>().set("withdraw_cash_status",billLine.getWithdrawCashStatus()).set("withdraw_apply_check_time",date).set("lock_version","(lock_version+1)").eq("id",billLine.getId());
        int num = billLineMapper.update(billLine,updateWrapper);
        if(num>0){
            LoginUser currentUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            MkBillLine mkBillLine = billLineMapper.selectById(billLine.getId());
            MkBillLineHistory billLineHistory = new MkBillLineHistory();
            BeanUtils.copyProperties(mkBillLine,billLineHistory);
            billLineHistory.setCreateTime(date);
            billLineHistory.setCreateBy(currentUser.getUsername());
            billLineHistory.setUpdateTime(null);
            billLineHistory.setUpdateBy(null);
            billLineHistory.setBillLineId(mkBillLine.getId());
            billLineHistory.setId(IdWorker.getIdStr(billLineHistory));
            billLineHistoryMapper.insert(billLineHistory);
        }

        return num;
    }

    @Override
    public MkBillLine findById(String id) {
        if(StringUtils.isBlank(id)){
            return null;
        }
        MkBillLine billLine = new MkBillLine();
        billLine.setId(id);
        List<MkBillLine> billLines = billLineMapper.findForPage(billLine);
        return (null==billLines || billLines.size()<1) ? null:billLines.get(0);
    }

    @Override
    public int numByCondation(QueryWrapper<MkBillLine> qw) {

        return billLineMapper.selectCount(qw);
    }

}
